#include "ColorPickerWidget.h"
#include "brushrenderframe.h"
#include "LeGraphicsView/Solarized.h"

#include <QDebug>
#include <QGridLayout>
#include <QLabel>
#include <QMouseEvent>
#include <QPainter>

const QSize ColorPickerWidget::g_iconSize = QSize(16, 16);

ColorPickerWidget::ColorPickerWidget(QWidget *parent):
    QWidget(parent)
{
    setMouseTracking(true);

    auto grid = new QGridLayout();
    setLayout(grid);

    auto label = new QLabel("Background");
    label->setAlignment(Qt::AlignHCenter|Qt::AlignVCenter);
    grid->addWidget(label, 0, 1, 1, 2);
    m_labelList.append(label);
    label = new QLabel("Content");
    label->setAlignment(Qt::AlignHCenter|Qt::AlignVCenter);
    grid->addWidget(label, 0, 3, 1, 4);
    m_labelList.append(label);
    label = new QLabel("Foreground");
    label->setAlignment(Qt::AlignHCenter|Qt::AlignVCenter);
    grid->addWidget(label, 0, 7, 1, 2);
    m_labelList.append(label);

    grid->addWidget(createFrame(Solarized::base03, "Background highlight"),
                    1, 1, 1, 1);
    grid->addWidget(createFrame(Solarized::base02, "Background"),
                    1, 2, 1, 1);
    grid->addWidget(createFrame(Solarized::base01, "Comments"),
                    1, 3, 1, 1);
    grid->addWidget(createFrame(Solarized::base00, "Default"),
                    1, 4, 1, 1);
    grid->addWidget(createFrame(Solarized::base0, "Emphasised"),
                    1, 5, 1, 1);
    grid->addWidget(createFrame(Solarized::base1, "Highlighted"), // ?
                    1, 6, 1, 1);
    grid->addWidget(createFrame(Solarized::base2, "Foreground highlight"),
                    1, 7, 1, 1);
    grid->addWidget(createFrame(Solarized::base3, "Foreground"),
                    1, 8, 1, 1);

    label = new QLabel("Accents");
    label->setAlignment(Qt::AlignHCenter|Qt::AlignVCenter);
    grid->addWidget(label, 2, 1, 1, 9);
    m_labelList.append(label);

    label = new QLabel("Darkest");
    label->setAlignment(Qt::AlignHCenter|Qt::AlignVCenter);
    grid->addWidget(label, 3, 0, 1, 1);
    m_labelList.append(label);

    grid->addWidget(createFrame(darkest(Solarized::yellow), "Darkest yellow"),
                    3, 1, 1, 1);
    grid->addWidget(createFrame(darkest(Solarized::orange), "Darkest orange"),
                    3, 2, 1, 1);
    grid->addWidget(createFrame(darkest(Solarized::red), "Darkest red"),
                    3, 3, 1, 1);
    grid->addWidget(createFrame(darkest(Solarized::magenta), "Darkest magenta"),
                    3, 4, 1, 1);
    grid->addWidget(createFrame(darkest(Solarized::violet), "Darkest violet"),
                    3, 5, 1, 1);
    grid->addWidget(createFrame(darkest(Solarized::blue), "Darkest blue"),
                    3, 6, 1, 1);
    grid->addWidget(createFrame(darkest(Solarized::cyan), "Darkest cyan"),
                    3, 7, 1, 1);
    grid->addWidget(createFrame(darkest(Solarized::green), "Darkest green"),
                    3, 8, 1, 1);


    label = new QLabel("Darker");
    label->setAlignment(Qt::AlignHCenter|Qt::AlignVCenter);
    grid->addWidget(label, 4, 0, 1, 1);
    m_labelList.append(label);

    grid->addWidget(createFrame(darker(Solarized::yellow), "Darker yellow"),
                    4, 1, 1, 1);
    grid->addWidget(createFrame(darker(Solarized::orange), "Darker orange"),
                    4, 2, 1, 1);
    grid->addWidget(createFrame(darker(Solarized::red), "Darker red"),
                    4, 3, 1, 1);
    grid->addWidget(createFrame(darker(Solarized::magenta), "Darker magenta"),
                    4, 4, 1, 1);
    grid->addWidget(createFrame(darker(Solarized::violet), "Darker violet"),
                    4, 5, 1, 1);
    grid->addWidget(createFrame(darker(Solarized::blue), "Darker blue"),
                    4, 6, 1, 1);
    grid->addWidget(createFrame(darker(Solarized::cyan), "Darker cyan"),
                    4, 7, 1, 1);
    grid->addWidget(createFrame(darker(Solarized::green), "Darker green"),
                    4, 8, 1, 1);

    label = new QLabel("Nominal");
    label->setAlignment(Qt::AlignHCenter|Qt::AlignVCenter);
    grid->addWidget(label, 5, 0, 1, 1);
    m_labelList.append(label);

    grid->addWidget(createFrame(nominal(Solarized::yellow), "Nominal yellow"),
                    5, 1, 1, 1);
    grid->addWidget(createFrame(nominal(Solarized::orange), "Nominal orange"),
                    5, 2, 1, 1);
    grid->addWidget(createFrame(nominal(Solarized::red), "Nominal red"),
                    5, 3, 1, 1);
    grid->addWidget(createFrame(nominal(Solarized::magenta), "Nominal magenta"),
                    5, 4, 1, 1);
    grid->addWidget(createFrame(nominal(Solarized::violet), "Nominal violet"),
                    5, 5, 1, 1);
    grid->addWidget(createFrame(nominal(Solarized::blue), "Nominal blue"),
                    5, 6, 1, 1);
    grid->addWidget(createFrame(nominal(Solarized::cyan), "Nominal cyan"),
                    5, 7, 1, 1);
    grid->addWidget(createFrame(nominal(Solarized::green), "Nominal green"),
                    5, 8, 1, 1);

    label = new QLabel("Lighter");
    label->setAlignment(Qt::AlignHCenter|Qt::AlignVCenter);
    grid->addWidget(label, 6, 0, 1, 1);
    m_labelList.append(label);

    grid->addWidget(createFrame(lighter(Solarized::yellow), "Lighter yellow"),
                    6, 1, 1, 1);
    grid->addWidget(createFrame(lighter(Solarized::orange), "Lighter orange"),
                    6, 2, 1, 1);
    grid->addWidget(createFrame(lighter(Solarized::red), "Lighter red"),
                    6, 3, 1, 1);
    grid->addWidget(createFrame(lighter(Solarized::magenta), "Lighter magenta"),
                    6, 4, 1, 1);
    grid->addWidget(createFrame(lighter(Solarized::violet), "Lighter violet"),
                    6, 5, 1, 1);
    grid->addWidget(createFrame(lighter(Solarized::blue), "Lighter blue"),
                    6, 6, 1, 1);
    grid->addWidget(createFrame(lighter(Solarized::cyan), "Lighter cyan"),
                    6, 7, 1, 1);
    grid->addWidget(createFrame(lighter(Solarized::green), "Lighter green"),
                    6, 8, 1, 1);

    label = new QLabel("Lightest");
    label->setAlignment(Qt::AlignHCenter|Qt::AlignVCenter);
    grid->addWidget(label, 7, 0, 1, 1);
    m_labelList.append(label);

    grid->addWidget(createFrame(lightest(Solarized::yellow), "Lightest yellow"),
                    7, 1, 1, 1);
    grid->addWidget(createFrame(lightest(Solarized::orange), "Lightest orange"),
                    7, 2, 1, 1);
    grid->addWidget(createFrame(lightest(Solarized::red), "Lightest red"),
                    7, 3, 1, 1);
    grid->addWidget(createFrame(lightest(Solarized::magenta), "Lightest magenta"),
                    7, 4, 1, 1);
    grid->addWidget(createFrame(lightest(Solarized::violet), "Lightest violet"),
                    7, 5, 1, 1);
    grid->addWidget(createFrame(lightest(Solarized::blue), "Lightest blue"),
                    7, 6, 1, 1);
    grid->addWidget(createFrame(lightest(Solarized::cyan), "Lightest cyan"),
                    7, 7, 1, 1);
    grid->addWidget(createFrame(lightest(Solarized::green), "Lightest green"),
                    7, 8, 1, 1);

    setLabelVisible(false);

    m_hoveredColor = m_selectedColor = m_colorToFrame.keys().first();
    m_colorToFrame.value(m_hoveredColor.name())->setFrameShadow(QFrame::Sunken);
    m_colorToFrame.value(m_selectedColor.name())->setFrameShadow(QFrame::Raised);

}

void ColorPickerWidget::setLabelVisible(bool visible)
{
    for (auto label: m_labelList)
        label->setVisible(visible);
}

QColor ColorPickerWidget::selectedColor() const
{
    return m_selectedColor;
}

void ColorPickerWidget::setSelectedColor(const QColor &color)
{
    if (!m_colorToFrame.contains(color.name()))
        return;

    m_colorToFrame.value(m_selectedColor.name())->setFrameShadow(QFrame::Plain);
    m_selectedColor = color;
    m_colorToFrame.value(m_selectedColor.name())->setFrameShadow(QFrame::Sunken);
}

QColor ColorPickerWidget::hoveredColor() const
{
    return m_hoveredColor;
}

void ColorPickerWidget::setHoveredColor(const QColor &color)
{
    if (!m_colorToFrame.contains(color.name()))
        return;

    if (m_hoveredColor == color)
        return;

    m_colorToFrame.value(m_hoveredColor.name())->setFrameShadow(QFrame::Plain);
    m_hoveredColor = color;
    m_colorToFrame.value(m_hoveredColor.name())->setFrameShadow(QFrame::Raised);
    m_colorToFrame.value(m_selectedColor.name())->setFrameShadow(QFrame::Sunken);

    emit colorHovered(color);
}

BrushRenderFrame *ColorPickerWidget::createFrame(const QColor &color, const QString &toolTip)
{
    auto frame = new BrushRenderFrame();
    frame->setFrameShape(QFrame::Panel);
    frame->setLineWidth(1);
    frame->setMinimumSize(g_iconSize);
    frame->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
    frame->setAttribute(Qt::WA_TransparentForMouseEvents);
    frame->setBrush(QBrush(color, Qt::SolidPattern));
    frame->setToolTip(toolTip);

    m_colorToFrame.insert(color.name(), frame);

    return frame;
}

QColor ColorPickerWidget::darkest(const QColor &color)
{
    return color.darker(166);
}

QColor ColorPickerWidget::darker(const QColor &color)
{
    return color.darker(133);
}

QColor ColorPickerWidget::nominal(const QColor &color)
{
    return color;
}

QColor ColorPickerWidget::lighter(const QColor &color)
{
    return color.lighter(133);
}

QColor ColorPickerWidget::lightest(const QColor &color)
{
    return color.lighter(166);
}

QSize ColorPickerWidget::sizeHint() const
{
    return QSize(8*g_iconSize.width(), 7*g_iconSize.height());
}

void ColorPickerWidget::mousePressEvent(QMouseEvent *event)
{
    Q_UNUSED(event)
    event->accept();
    setSelectedColor(m_hoveredColor);
    emit colorClicked(m_hoveredColor);
}

void ColorPickerWidget::mouseMoveEvent(QMouseEvent *event)
{
    for (auto color: m_colorToFrame.keys())
    {
        if (m_colorToFrame.value(color)->geometry().contains(event->pos()))
        {
            setHoveredColor(QColor(color));
            return;
        }
    }
}

void ColorPickerWidget::mouseDoubleClickEvent(QMouseEvent *event)
{
    for (auto color: m_colorToFrame.keys())
    {
        if (m_colorToFrame.value(color)->geometry().contains(event->pos()))
        {
            emit colorDoubleClicked(m_selectedColor);
            return;
        }
    }
}

void ColorPickerWidget::enterEvent(QEvent *event)
{
    Q_UNUSED(event)
    m_colorToFrame.value(m_hoveredColor.name())->setFrameShadow(QFrame::Raised);
    m_colorToFrame.value(m_selectedColor.name())->setFrameShadow(QFrame::Sunken);
    setHoveredColor(m_selectedColor);
}

void ColorPickerWidget::leaveEvent(QEvent *event)
{
    Q_UNUSED(event)
    m_colorToFrame.value(m_hoveredColor.name())->setFrameShadow(QFrame::Plain);
    m_colorToFrame.value(m_selectedColor.name())->setFrameShadow(QFrame::Sunken);
    setHoveredColor(m_selectedColor);
}
